#include <stdlib.h>
#include "flv.h"

const char *const flv_track_str[256] = {
	[FLV_TRACK_AUDIO] = "audio",
	[FLV_TRACK_VIDEO] = "video",
	[FLV_TRACK_SCRIPT] = "script",
};

const char *const flv_acodec_str[16] = {
	[FLV_AUDIO_PCM] = "pcm",
	[FLV_AUDIO_ADPCM] = "adpcm",
	[FLV_AUDIO_MP3] = "mp3",
	[FLV_AUDIO_PCMLE] = "pcmle",
	[FLV_AUDIO_NELLYMOSER_16KHZ_MONO] = "nellymoser16k",
	[FLV_AUDIO_NELLYMOSER_8KHZ_MONO] = "nellymoser8k",
	[FLV_AUDIO_NELLYMOSER] = "nellymoser",
	[FLV_AUDIO_G711_A_LAW] = "g711a",
	[FLV_AUDIO_G711_MU_LAW] = "g711u",
	[9] = "reserved",
	[FLV_AUDIO_AAC] = "aac",
	[FLV_AUDIO_SPEEX] = "speex",
	[FLV_AUDIO_MP3_8K] = "mp38k",
	[FLV_AUDIO_DEVICE_SPECIFIC] = "device",
};

const char *const flv_arate_str[4] = {
	[FLV_AUDIO_5512HZ] = "5.5k",
	[FLV_AUDIO_11025HZ] = "11k",
	[FLV_AUDIO_22050HZ] = "22k",
	[FLV_AUDIO_44100HZ] = "44k",
};

const char *const flv_adepth_str[2] = {
	[FLV_AUDIO_8BIT] = "8bit",
	[FLV_AUDIO_16BIT] = "16bit",
};

const char *const flv_amode_str[2] = {
	[FLV_AUDIO_MONO] = "mono",
	[FLV_AUDIO_STEREO] = "stereo",
};

const char *const flv_vframe_str[16] = {
	[FLV_VIDEO_KEY] = "key",
	[FLV_VIDEO_INTER] = "inter",
	[FLV_VIDEO_DISPOSABLE_INTER] = "dispo",
	[FLV_VIDEO_GENERATED_KEY] = "gen",
	[FLV_VIDEO_INFO] = "info",
};

const char *const flv_vcodec_str[16] = {
	[FLV_VIDEO_JPEG] = "jpeg",
	[FLV_VIDEO_H263] = "h263",
	[FLV_VIDEO_FSV1] = "fsv1",
	[FLV_VIDEO_VP6F] = "vp6f",
	[FLV_VIDEO_VP6A] = "vp6a",
	[FLV_VIDEO_FSV2] = "fsv2",
	[FLV_VIDEO_H264] = "h264",
};

/**
 * flvname()
 * @return: the field name or a number if null.
 */
const char *flvname(const char *const *names, unsigned index)
{
	static char buf[4];
	char *s;
	index &= 0xff;
	if (names[index])
		return names[index];
	s = &buf[3];
	do {
		s--;
		*s = index % 10 + '0';
		index /= 10;
	} while (index);
	return s;
}

static const size_t tagbuf_initial_size = 65536;

void tagbuf_clear(struct tagbuf *b)
{
	b->used = 0;
	b->read = 0;
	b->is_tag = 1;
	b->is_linear = 1;
	b->hdrlen = 0;
	b->len = 0;
}

/**
 * tagbuf_alloc()
 * @return: NULL on error with errno set by malloc().
 */
struct tagbuf *tagbuf_alloc(void)
{
	struct tagbuf *r;
	r = malloc(sizeof(*r));
	if (!r)
		return 0;
	r->data = malloc(tagbuf_initial_size);
	r->allocated = tagbuf_initial_size;
	tagbuf_clear(r);
	return r;
}

void tagbuf_free(struct tagbuf *b)
{
	free(b->data);
	free(b);
}

/**
 * tagbuf_realloc()
 * @return: NULL on error with errno set by realloc().
 */
struct tagbuf *tagbuf_realloc(struct tagbuf *b, size_t size)
{
	void *n;
	n = realloc(b->data, size);
	if (!n)
		return 0;
	b->data = n;
	return b;
}
